package org.c41.reflect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.c41.system.ImpossibleException;
import org.c41.system.Tools;

@Tools
public final class MockFactory {

	private MockFactory(){
		throw new ImpossibleException();
	}
	
	private static ClassLoader dcloader = MockFactory.class.getClassLoader();
	
	public static Object mock(Class<?>[] interfaces, InvocationHandler handler){
		return Proxy.newProxyInstance(dcloader, interfaces, handler);
	}
	
	public static <T> T mock(Class<T> interf, InvocationHandler handler){
		return (T) Proxy.newProxyInstance(dcloader, new Class<?>[]{interf}, handler);
	}

	public static <T> T mock(T t, InvocationHandler handler){
		return (T) new Cglib(handler).getInstance(t);
	}
	
}

class Cglib implements MethodInterceptor{

	private InvocationHandler handler;
	private Object obj;
	
	Cglib(InvocationHandler handler){
		this.handler=handler;
	}

	Object getInstance(Object target) {  
		Enhancer enhancer = new Enhancer();  
		enhancer.setSuperclass(target.getClass());  
		enhancer.setCallback(this);  
		this.obj=target;
		return enhancer.create();  
	}  
	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		return handler.invoke(this.obj, method, args);
	}

}